package com.realtyManage.springboot.Interceptor;

import com.realtyManage.springboot.Model.Security;
import com.realtyManage.springboot.Model.Vo.RegEntity;
import com.realtyManage.springboot.Utils.SpringContextUtil;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWTLoginFilter
 ** 验证用户名密码正确后，生成一个token，并将token返回给客户端
 * 该类继承自UsernamePasswordAuthenticationFilter，重写其中2个方法
 * attemptAuthentication ：接收并解析用户凭证。
 * successfulAuthentication ：用户成功登录后调用方法生成token。
 * @Author 杭州素色网络科技有限公司
 * @Date 2019/6/30
 **/
public class JWTLoginFilter extends UsernamePasswordAuthenticationFilter {

    private AuthenticationManager authenticationManager;

    public JWTLoginFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    // 接收并解析用户凭证
    @Override
    public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) throws AuthenticationException {
        /*try {*/
            RegEntity user = new RegEntity();
            user.setUsername(req.getParameter("username"));
            user.setPassword(req.getParameter("password"));
            //RegEntity user = new ObjectMapper().readValue(req.getInputStream(), RegEntity.class);
            return authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            user.getUsername(),
                            user.getPassword(),
                            new ArrayList<>())
            );
        /*} catch (IOException e) {
            throw new RuntimeException(e);
        }*/
    }

    // 用户成功登录后调用方法生成token
    @Override
    protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain, Authentication auth) throws IOException, ServletException {
        Security securityCfg = (Security)SpringContextUtil.getBean("security");
        Map<String,Object> claims = new HashMap<String,Object>();//创建payload的私有声明
        claims.put("uid", "");
        claims.put("level", ((org.springframework.security.core.userdetails.User) auth.getPrincipal()).getAuthorities());
        String token = Jwts.builder()
                .setClaims(claims)//如果有私有声明，一定要先设置这个自己创建的私有的声明，这个是给builder的claim赋值，一旦写在标准的声明赋值之后，就是覆盖了标准的声明
                //.setId(id)//设置jti(JWT ID)：是JWT的唯一标识，根据业务需要，这个可以设置为一个不重复的值，主要用来作为一次性token,从而回避重放攻击。
                .setSubject(((org.springframework.security.core.userdetails.User) auth.getPrincipal()).getUsername())//主体
                .setExpiration(new Date(System.currentTimeMillis() + 60 * 60 * 24 * 365 * 1000))
                .signWith(SignatureAlgorithm.HS512, securityCfg.getKey())
                .compact();
        res.addHeader("Authorization", "Bearer " + token);
    }

}
